package blazingbubble.network.lobby;

import moltencore.network.protocol.*;
import org.apache.log4j.Logger;

import java.net.SocketException;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;

import spark.network.*;
import spark.network.protocol.*;

/**
 * Demon handling the player list and creation of games.
 */
public class LobbyDemon extends Demon implements Runnable {
	private static Logger logger = Logger.getLogger(LobbyDemon.class);

	private LobbyDemonHandler handler;
	private LobbyStrategyFactory strategyFactory;

	public LobbyDemon(
			ServerConnection serverConnection, Sender sender,
			LobbyStrategyFactory strategyFactory) throws SocketException {
		super();
		handler = new LobbyDemonHandler(serverConnection, sender);
		setTimeAdjuster(handler);
		this.strategyFactory = strategyFactory;
	}

	public LobbyDemon(
			int queryPort, ServerConnection serverConnection, ServerSender sender,
			LobbyStrategyFactory strategyFactory) throws SocketException {
		super(queryPort);
		handler = new LobbyDemonHandler(serverConnection, sender);
		this.strategyFactory = strategyFactory;
	}

	public void setPreLoginResponseListener(IPreLoginResponseResultListener preLoginResponseListener) {
		handler.setPreLoginResponseListener(preLoginResponseListener);
	}

	@Override
	protected void processPacket(DatagramPacket packet, long receiveTime) {
		byte[] packetData = packet.getData();
		InetSocketAddress source = Util.extractInetSocketAddress(packet);
		switch(Base.getType(packetData)) {
			case Acknowledgement.TYPE:
				logger.debug("Received: Acknowledgement from " + source);
				handler.handle(Acknowledgement.create(packetData, receiveTime), source);
				break;
			case PreLoginResponse.TYPE:
				logger.debug("Received: PreLoginResponse from " + source);
				handler.handle(PreLoginResponse.create(packetData, receiveTime), source);
				break;
			case ClockSyncReq.TYPE:
				logger.debug("Received: ClockSyncReq from " + source);
				handler.handle(ClockSyncReq.create(packetData, receiveTime), source);
				break;
			case ClockAdjustNotice.TYPE:
				logger.debug("Received: ClockAdjustNotice from " + source);
				handler.handle(ClockAdjustNotice.create(packetData, receiveTime), source);
				break;
			case LoginResponse.TYPE:
				logger.debug("Received: LoginResponse from " + source);
				handler.handle(LoginResponse.create(packetData, receiveTime), source, strategyFactory.getLoginResponseStrategy());
				break;
			case CreateGameResponse.TYPE:
				logger.debug("Received: CreateGameResponse from " + source);
				handler.handle(CreateGameResponse.create(packetData, receiveTime), source, strategyFactory.getCreateGameResponseStrategy());
				break;
			case GameListGameData.TYPE:
				logger.debug("Received: GameListGameData from " + source);
				handler.handle(GameListGameData.create(packetData, receiveTime), source, strategyFactory.getGameListGameDataStrategy());
				break;
			case GameListSendingEnd.TYPE:
				logger.debug("Received: GameListSendingEnd from " + source);
				handler.handle(GameListSendingEnd.create(packetData, receiveTime), source, strategyFactory.getGameListSendingEndStrategy());
				break;
			default:
				//TODO : when done with programming the protocol remove this warn message
				//unknown protocol type received, ignore it
				logger.warn("Unknown protocol type received " + Integer.toHexString(Base.getType(packet.getData())) + ". Forgot to handle this protocol type?");
				break;
		}
	}
}